﻿using System;
using System.Collections.Generic;
using System.Text;
using ExpressionUtil.Common;

namespace ExpressionUtil.Parser.Handler
{
    /// <summary>
    /// 运算符处理程序
    /// </summary>
    internal class OperatorHandler : ParseHandlerBase
    {
        /// <summary>
        /// 默认构造函数
        /// </summary>
        public OperatorHandler()
        {
            this.next = new ConstNumberHandler();
        }

        /// <summary>
        /// 解析元素
        /// </summary>
        /// <param name="context">解析参数</param>
        /// <param name="element">需要解析的元素</param>
        /// <returns>是否已解析</returns>
        protected override bool ParseCore(string element, ParseContext context)
        {
            bool ret = false;
            if (Common.StringHelper.IsOperatorChar(element[0]))
            {
                this.ParseOperator(element, context);
                ret = true;
            }
            return ret;
        }

        /// <summary>
        /// 解析运算符
        /// </summary>
        /// <param name="op2">当前的运算符</param>
        /// <param name="context">解析参数</param>
        private void ParseOperator(string op2, ParseContext context)
        {
            string op1 = null;
            if (op2 == "-" || op2 == "+")
            {
                //正负号特殊处理
                char prevChar = context.Scanner.PrevChar;
                bool hasLeft = prevChar != char.MaxValue && prevChar != '(' && prevChar != ',' && !StringHelper.IsNoneUnitaryOperatorChar(prevChar);
                if (!hasLeft)
                {
                    op2 = "Unitary" + op2;
                }
            }
            if (context.OperatorStack.Count > 0)
            {
                op1 = context.OperatorStack.Pop();
                while (true)
                {
                    if (op1.EndsWith("("))
                    {
                        context.OperatorStack.Push(op1);
                        context.OperatorStack.Push(op2);
                        break;
                    }
                    else if (ParseContext.OperatorPriority.ContainsKey(op1) && ParseContext.OperatorPriority.ContainsKey(op2))
                    {
                        int priority1 = ParseContext.OperatorPriority[op1];
                        int priority2 = ParseContext.OperatorPriority[op2];
                        if (priority2 > priority1)
                        {
                            context.OperatorStack.Push(op1);
                            context.OperatorStack.Push(op2);
                            break;
                        }
                        else
                        {
                            CheckHelper.CreateHandlerExists(op1, "Unknow operator.");
                            ParseContext.CreateHandlerMap[op1](context);
                            if (context.OperatorStack.Count > 0)
                            {
                                op1 = context.OperatorStack.Pop();
                            }
                            else
                            {
                                context.OperatorStack.Push(op2);
                                break;
                            }
                        }
                    }
                    else
                    {
                        throw new FormatException("Unknow operator.");
                    }
                }
            }
            else
            {
                context.OperatorStack.Push(op2);
            }
        }
    }
}
